﻿// Copyright © 2010 Silvestru Iapascurta.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see license.txt for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Data;
using System.Windows.Forms;
using FeedDotNet.Common;
using Karoro.Properties;

namespace Karoro
{
    public static class Formatting
    {
        public static string GenerateHtmlView(TreeNode node, KaroroForm instance, int startIndex)
        {
            int requestedItems = Karoro.Properties.Settings.Default.itemsPerPage;
            long totalItems = 0;
            long retrievedItems = 0;
            Style userStyle = instance.Themes.Find(KaroroForm.CurrentStyle);
            StringBuilder document = new StringBuilder(51200);
            StringBuilder categories = new StringBuilder(46080);
            StringBuilder items = new StringBuilder(20480);
            DataTable data = null;
            string last = null;

            if (userStyle == null)
                userStyle = instance.Themes.Find(KaroroForm.DefaultStyle);

            document.Append(userStyle.Html);
            document.Replace("%main_title%", node.Text);
            document.Replace("%style_path%", new Uri(userStyle.Path.FullName).AbsoluteUri);            

            string[] view_string = node.Tag.ToString().Split(';');

            switch (view_string[0])
            {
                case "feed":
                    data = Database.ReadFeed(0, int.Parse(view_string[1]), startIndex);
                    break;

                case "folder":
                    data = Database.ReadFeed(1, int.Parse(view_string[1]), startIndex);
                    break;

                default:
                    break;
            }

            totalItems = Database.GetItemCount(view_string[0], view_string[1]);

            for (int i = 0; i < data.Rows.Count; i++)
            {
                items.Append(userStyle.ItemBlock);
                items.Replace("%item_link%", (string)data.Rows[i]["url"]);

                if (!String.IsNullOrEmpty((string)data.Rows[i]["title"]))
                    items.Replace("%item_title%", (string)data.Rows[i]["title"]);
                else
                    items.Replace("%item_title%", data.Rows[i]["item_id"].ToString());

                if (!(data.Rows[i]["author"] is DBNull))
                    items.Replace("%author%", (string)data.Rows[i]["author"]);
                else
                    items.Replace("%author%", null);

                items.Replace("%item_date%", ((DateTime)data.Rows[i]["published_time"]).ToString(Karoro.Properties.Settings.Default.timeFormat));

                if (!(data.Rows[i]["content"] is DBNull))
                    items.Replace("%item_content%", Encoding.UTF8.GetString((byte[])data.Rows[i]["content"]));
                else
                    items.Replace("%item_content%", null);

                items.Replace("%item_source_title%", (string)data.Rows[i]["feed_name"]);
                items.Replace("%save_button%", String.Format("window.external.SaveItem({0})", data.Rows[i]["item_id"].ToString()));

                last = (string)data.Rows[i]["group_name"];

                // if we're last or the next one is a different group, clear buffer
                if (i == data.Rows.Count - 1 || last != (string)data.Rows[i + 1]["group_name"])
                {
                    categories.Append(userStyle.CategoryBlock);
                    categories.Replace("%category_title%", (string)data.Rows[i]["group_name"]);
                    categories.Replace(userStyle.ItemBlock, items.ToString());
                    items.Length = 0;
                }
            }

            retrievedItems += data.Rows.Count;
            
            document.Replace(
                "%currentpage%",
                (Math.Ceiling( (decimal)(startIndex + retrievedItems) / (decimal)requestedItems ).ToString())
                );

            document.Replace(
                "%totalpages%",
                (Math.Ceiling( (decimal)totalItems / (decimal)requestedItems ).ToString())
                );

            if (startIndex - requestedItems >= 0)
            {
                document.Replace("%previous_link%", "window.external.NavigatePage(" + requestedItems + ", " + (startIndex - requestedItems) + ")");
            }
            else
            {
                document.Replace("%previous_link%", null);
            }

            if (startIndex + requestedItems < totalItems)
            {
                document.Replace("%next_link%", "window.external.NavigatePage(" + requestedItems + ", " + (startIndex + requestedItems) + ")");
            }
            else
            {
                document.Replace("%next_link%", "");
            }

            document.Replace(userStyle.CategoryBlock, categories.ToString());

            return document.ToString();
        }

        private static string HumaneDate(DateTime time)
        {
            int span = (DateTime.Now.Date - time).Days;
            string formattedDate = null;
            string token = "ago";

            int week = 7;
            int month = 28;
            int year = 365;

            int years = span / year;
            int months = (span - year * (span / year)) / month;
            int weeks = (span - month * (span / month)) / week;
            int days = span - week * (span / week);

            if (years == 0 && months == 0 && weeks == 0 && days == 0)
            {
                return "Today";
            }

            if (years == 0 && months == 0 && weeks == 0 && days == 1)
            {
                return "Yesterday";
            }

            if (years == 1)
                formattedDate += "one year ";
            else if (years > 1)
                formattedDate += years + " years ";

            if (months == 1)
                formattedDate += " one month ";
            else if (months > 1)
                formattedDate += " " + months + " months ";

            if (weeks == 1)
                formattedDate += " one week ";
            else if (weeks > 1)
                formattedDate += " " + weeks + " weeks ";

            if (days == 1)
                formattedDate += " one day";
            else if (days > 1)
                formattedDate += " " + days + " days";

            formattedDate = formattedDate.TrimStart(' ');
            formattedDate = formattedDate.TrimEnd(' ');

            return (char.ToUpper(formattedDate[0]) + formattedDate.Substring(1).Replace("  ", ", ")) + " " + token;
        }
    }
}
